package com.zhangc.blog.admin.web.security;

import java.util.Collection;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.AccessDecisionManager;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.web.FilterInvocation;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import com.zhangc.blog.admin.service.AuthObjService;

/**
 * 功能描述:<br>
 *
 * @author wx:fdzhangc
 * @see [相关类/方法]（可选）
 * @since [产品/模块版本] （可选）
 */
@Component
public class UrlAccessDecisionManager implements AccessDecisionManager {
    private static final Logger logger = LoggerFactory.getLogger(UrlAccessDecisionManager.class);
    @Autowired
    AuthObjService authObjService;

    /**
     * 功能描述: <br>
     * 〈功能详细描述〉
     *
     * @param authentication 当前登录用户的角色信息
     * @param object         请求url信息
     * @param collection     当前url需要的角色信息
     * @return void
     * @author wx:fdzhangc
     */
    @Override
    public void decide(Authentication authentication, Object object, Collection<ConfigAttribute> collection)
            throws AccessDeniedException, InsufficientAuthenticationException {
        //TODO:判断此url是否有权限控制，有则判断权限，没有则直接放行---引入redis
        logger.info("decide:{}", object);
        String requestUrl = ((FilterInvocation) object).getRequestUrl();
        //TODO：特殊需要直接放行的--放入scm中
        if (requestUrl.contains("api/auth/login")) {
            return;
        }
        Set<String> authSource = authObjService.queryAllAuthObj();
        if (CollectionUtils.isEmpty(authSource)) {
            return;
        }
        //需要授权
        boolean needAuth = authSource.contains(requestUrl) || authSource.stream().anyMatch(a -> requestUrl.startsWith(a));
        if (!needAuth) {
            //不需要授权就能访问的
            return;
        }
        //剩下的就是需要授权才能访问的资源

        // ② 当前用户所具有的角色
        Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
        for (GrantedAuthority authority : authorities) {
            //只要包含其中一个角色即可访问
            if (authority.getAuthority().equals(requestUrl) || requestUrl.startsWith(authority.getAuthority())) {
                return;
            }
        }
        throw new AccessDeniedException("请联系管理员分配权限！");
    }

    @Override
    public boolean supports(ConfigAttribute configAttribute) {
        return true;
    }

    @Override
    public boolean supports(Class<?> aClass) {
        return true;
    }
}
